from fastapi import FastAPI

from fastapi.exceptions import RequestValidationError
from fastapi.responses import ORJSONResponse
from pydantic import ValidationError
from requests import Request
from starlette import status

from src.model import ResponseModel
from src.enum.exception import ExceptionEnum
from src.exception import ResponseException

app = FastAPI()

# 自定义异常处理程序
async def response_exception_handler(request: Request, exc: ResponseException):
    print(exc)
    return ORJSONResponse(
        status_code=exc.status_code,
        content=ResponseModel(
            msg=exc.message,
            code=exc.error_code,
        ).model_dump()
    )

# Not Found 异常
async def not_found_exception_handler(request: Request, exc):
    print(exc)
    return ORJSONResponse(
        status_code=status.HTTP_404_NOT_FOUND,
        content=ResponseModel(
            msg=ExceptionEnum.NOT_FOUND.msg,
            code=ExceptionEnum.NOT_FOUND.code,
        ).model_dump()
    )

# METHOD_NOT_ALLOWED 异常
async def method_not_allowed_exception_handler(request: Request, exc):
    print(exc)
    return ORJSONResponse(
        status_code=status.HTTP_405_METHOD_NOT_ALLOWED,
        content=ResponseModel(
            msg=ExceptionEnum.METHOD_NOT_ALLOWED.msg,
            code=ExceptionEnum.METHOD_NOT_ALLOWED.code,
        ).model_dump()
    )

# 验证异常
async def validation_exception_handler(request: Request, exc: ValidationError|RequestValidationError):
    print(exc)
    return ORJSONResponse(
        status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
        content=ResponseModel(
            msg=ExceptionEnum.INVALID_TOKEN_FIELD.msg,
            code=ExceptionEnum.INVALID_TOKEN_FIELD.code,
        ).model_dump()
    )

# 未定义异常
async def unhandled_exception_handler(request: Request, exc: Exception):
    print(exc)
    return ORJSONResponse(
        status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
        content=ResponseModel(
            msg=ExceptionEnum.INTERNAL_ERROR.msg,
            code=ExceptionEnum.INTERNAL_ERROR.code,
            data=str(exc)
        ).model_dump()
    )